package services

import (
	"fmt"
	"sync"

	"cdk.tf/go/stack/interfaces"
	"cdk.tf/go/stack/utils"
	"github.com/aws/constructs-go/constructs/v10"
	"github.com/aws/jsii-runtime-go"
	"github.com/cdktf/cdktf-provider-aws-go/aws/v17/subnet"
)

type SubnetService struct {
	subnets map[string]*subnet.Subnet
	mu      sync.RWMutex
}

func NewSubnetService() *SubnetService {
	return &SubnetService{
		subnets: make(map[string]*subnet.Subnet),
	}
}

func (s *SubnetService) CreateSubnet(scope constructs.Construct, id string, config *interfaces.SubnetConfig) (*subnet.Subnet, error) {
	// 验证CIDR块格式
	if !isValidCIDR(config.CidrBlock) {
		return nil, fmt.Errorf("invalid CIDR block: %s", config.CidrBlock)
	}

	// 验证VPC ID格式
	if err := utils.ValidateVPCID(config.VpcID); err != nil {
		return nil, err
	}

	subnetResource := subnet.NewSubnet(scope, jsii.String(id), &subnet.SubnetConfig{
		VpcId:               jsii.String(config.VpcID),
		CidrBlock:           jsii.String(config.CidrBlock),
		AvailabilityZone:    jsii.String(config.AvailabilityZone),
		MapPublicIpOnLaunch: jsii.Bool(config.MapPublicIPOnLaunch),
		Tags:                utils.ConvertTags(config.Tags),
	})

	// 添加名称标签
	if config.Name != "" {
		subnetResource.AddOverride(jsii.String("tags.Name"), jsii.String(config.Name))
	}

	s.mu.Lock()
	subnetID := utils.SafeDereference(subnetResource.Id())
	if subnetID != "" {
		s.subnets[subnetID] = &subnetResource
	}
	s.mu.Unlock()

	return &subnetResource, nil
}

func (s *SubnetService) GetSubnetByID(scope constructs.Construct, subnetID string) (*subnet.Subnet, error) {
	s.mu.RLock()
	defer s.mu.RUnlock()

	if subnetResource, exists := s.subnets[subnetID]; exists {
		return subnetResource, nil
	}

	return nil, fmt.Errorf("Subnet with ID %s not found", subnetID)
}

func (s *SubnetService) ListSubnets() map[string]*subnet.Subnet {
	s.mu.RLock()
	defer s.mu.RUnlock()

	result := make(map[string]*subnet.Subnet)
	for id, subnet := range s.subnets {
		result[id] = subnet
	}
	return result
}

func (s *SubnetService) GetSubnetsByVPC(vpcID string) map[string]*subnet.Subnet {
	s.mu.RLock()
	defer s.mu.RUnlock()

	result := make(map[string]*subnet.Subnet)
	for id, subnetResource := range s.subnets {
		if utils.SafeDereference(subnetResource.VpcId()) == vpcID {
			result[id] = subnetResource
		}
	}
	return result
}

func (s *SubnetService) GetSubnetsByAvailabilityZone(availabilityZone string) map[string]*subnet.Subnet {
	s.mu.RLock()
	defer s.mu.RUnlock()

	result := make(map[string]*subnet.Subnet)
	for id, subnetResource := range s.subnets {

		if utils.SafeDereference(subnetResource.AvailabilityZone()) == availabilityZone {
			result[id] = subnetResource
		}
	}
	return result
}

func (s *SubnetService) GetSubnetsByTags(tags map[string]string) map[string]*subnet.Subnet {
	s.mu.RLock()
	defer s.mu.RUnlock()

	result := make(map[string]*subnet.Subnet)
	for id, subnetResource := range s.subnets {
		if s.subnetMatchesTags(subnetResource, tags) {
			result[id] = subnetResource
		}
	}
	return result
}

func (s *SubnetService) subnetMatchesTags(subnetResource *subnet.Subnet, tags map[string]string) bool {
	// 简化实现
	return len(tags) == 0
}
